package cn.chendd.redis.configuration;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;

import static cn.chendd.redis.constants.RedisConstants.*;

/**
 * Redis 配置类
 *
 * @author chendd
 * @date 2023/5/16 15:40
 */
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConfiguration {

    @Bean(WRITE_LETTUCE_CONNECTION_FACTORY)
    @Primary
    public LettuceConnectionFactory writeLettuceConnectionFactory(@Autowired @Qualifier("spring.redis-org.springframework.boot.autoconfigure.data.redis.RedisProperties")
                                                                              RedisProperties redisProperties) {
        RedisProperties.Lettuce lettuce = redisProperties.getLettuce();
        RedisProperties.Pool pool = lettuce.getPool();
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle (pool.getMaxIdle());
        poolConfig.setMinIdle (pool.getMinIdle());
        poolConfig.setMaxTotal(pool.getMaxActive());
        poolConfig.setMaxWait(pool.getMaxWait());
        LettucePoolingClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(poolConfig)
                .commandTimeout(redisProperties.getTimeout())
                .shutdownTimeout(lettuce.getShutdownTimeout())
                .build();
        LettuceConnectionFactory factory = new LettuceConnectionFactory(this.writeConfig(redisProperties) , clientConfiguration);
        return factory;
    }

    @Bean(READ1_LETTUCE_CONNECTION_FACTORY)
    public LettuceConnectionFactory read1LettuceConnectionFactory(@Autowired @Qualifier("spring.redis-org.springframework.boot.autoconfigure.data.redis.RedisProperties")
                                                                              RedisProperties redisProperties) {
        RedisProperties.Lettuce lettuce = redisProperties.getLettuce();
        RedisProperties.Pool pool = lettuce.getPool();
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle (pool.getMaxIdle());
        poolConfig.setMinIdle (pool.getMinIdle());
        poolConfig.setMaxTotal(pool.getMaxActive());
        poolConfig.setMaxWait(pool.getMaxWait());
        LettucePoolingClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(poolConfig)
                .commandTimeout(redisProperties.getTimeout())
                .shutdownTimeout(lettuce.getShutdownTimeout())
                .build();
        LettuceConnectionFactory factory = new LettuceConnectionFactory(this.read1Config() , clientConfiguration);
        factory.setShareNativeConnection(false);
        return factory;
    }

    @Bean(READ2_LETTUCE_CONNECTION_FACTORY)
    public LettuceConnectionFactory read2LettuceConnectionFactory(@Autowired @Qualifier("spring.redis-org.springframework.boot.autoconfigure.data.redis.RedisProperties")
                                                                              RedisProperties redisProperties) {
        RedisProperties.Lettuce lettuce = redisProperties.getLettuce();
        RedisProperties.Pool pool = lettuce.getPool();
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle (pool.getMaxIdle());
        poolConfig.setMinIdle (pool.getMinIdle());
        poolConfig.setMaxTotal(pool.getMaxActive());
        poolConfig.setMaxWait(pool.getMaxWait());
        LettucePoolingClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(poolConfig)
                .commandTimeout(redisProperties.getTimeout())
                .shutdownTimeout(lettuce.getShutdownTimeout())
                .build();
        LettuceConnectionFactory factory = new LettuceConnectionFactory(this.read2Config() , clientConfiguration);

        factory.setShareNativeConnection(false);
        return factory;
    }

    private RedisStandaloneConfiguration writeConfig(RedisProperties redisProperties) {
        RedisStandaloneConfiguration standalone = new RedisStandaloneConfiguration(redisProperties.getHost() , redisProperties.getPort());
        standalone.setUsername(redisProperties.getUsername());
        standalone.setPassword(redisProperties.getPassword());
        standalone.setDatabase(redisProperties.getDatabase());
        return standalone;
    }

    private RedisStandaloneConfiguration read1Config() {
        RedisStandaloneConfiguration standalone = new RedisStandaloneConfiguration(this.first.getHost() , this.first.getPort());
        standalone.setUsername(this.first.getUsername());
        standalone.setPassword(this.first.getPassword());
        standalone.setDatabase(this.first.getDatabase());
        return standalone;
    }

    private RedisStandaloneConfiguration read2Config() {
        RedisStandaloneConfiguration standalone = new RedisStandaloneConfiguration(this.second.getHost() , this.second.getPort());
        standalone.setUsername(this.second.getUsername());
        standalone.setPassword(this.second.getPassword());
        standalone.setDatabase(this.second.getDatabase());
        return standalone;
    }

    private RedisRead first;

    private RedisRead second;

    static class RedisRead {

        private int database;

        private String host;

        private String username;

        private String password;

        private int port;

        public int getDatabase() {
            return database;
        }

        public void setDatabase(int database) {
            this.database = database;
        }

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public int getPort() {
            return port;
        }

        public void setPort(int port) {
            this.port = port;
        }
    }

    public RedisRead getFirst() {
        return first;
    }

    public void setFirst(RedisRead first) {
        this.first = first;
    }

    public RedisRead getSecond() {
        return second;
    }

    public void setSecond(RedisRead second) {
        this.second = second;
    }
}
